using BlazorServerVisitorDemo.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.JSInterop;
using System.Collections.Concurrent;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddScoped<CircuitHandler, CircuitTracker>();

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseAntiforgery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

public class CircuitClientInfo
{
    public string CircuitId { get; set; } = "";
    public DateTimeOffset JoinDateTime { get; set; } = DateTimeOffset.Now;
}

public static class CircuitTrackerGlobalInfo
{
    public static ConcurrentDictionary<string, CircuitClientInfo> CircuitClients { get; set; } = new();
    public static ConcurrentDictionary<string, string> VisitorClients { get; set; } = new();
}

public class CircuitTracker : CircuitHandler
{
    private CircuitClientInfo _circuitInfo = new();
    private string _visitorId = "";

    public int ConnectionCount => CircuitTrackerGlobalInfo.CircuitClients.Count;
    public int VisitorCount => CircuitTrackerGlobalInfo.VisitorClients.GroupBy(x => x.Value).Count();

    public string CircuitId => _circuitInfo.CircuitId;
    public string VisitorId => _visitorId;

    public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        _circuitInfo.CircuitId = circuit.Id;
        _circuitInfo.JoinDateTime = DateTimeOffset.Now;
        CircuitTrackerGlobalInfo.CircuitClients.TryAdd(circuit.Id, _circuitInfo);
        return Task.CompletedTask;
    }

    public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        CircuitTrackerGlobalInfo.CircuitClients.TryRemove(circuit.Id, out _);
        CircuitTrackerGlobalInfo.VisitorClients.TryRemove(circuit.Id, out _);
        return Task.CompletedTask;
    }

    public void VisitorRegister(string visitorId)
    {
        _visitorId = visitorId;
        CircuitTrackerGlobalInfo.VisitorClients.TryAdd(CircuitId, visitorId);
    }
}